This document gives insights on school location data available for Nairobi, Kenya.

We look at data from WorldBank and OpenStreetMap (via Overpass API). For OpenStreetMap a little processing is necessary due to its datamodel and possibility of dual representation of schools as POI and building footprint. In the following chunk we download the data from OSM and check for overlaps of footprints and POIs.

osm_schools |> nrow()
## [1] 1877
selected_cols <- grep("education|name|osm_id|amenity", names(osm_schools), ignore.case = TRUE)
osm_schools <- osm_schools |> select(all_of(selected_cols))

osm_schools <- osm_schools |>  st_filter(nairobi_boundary)


schools_wb <- schools_wb |>
  st_transform(4326) |>
  st_filter(nairobi_boundary)

schools_wb |> names()
##  [1] "OBJECTID"   "CODE"       "SCHOOL_NAM" "LEVEL"      "Status"    
##  [6] "County"     "DISTRICT"   "ZONE"       "SUB_COUNTY" "Ward"      
## [11] "X_Coord"    "Y_Coord"    "Source"     "geometry"

# How many schools overlap within different distances
wb50_osm <- osm_schools |> st_transform(32637) |>
  st_filter(schools_wb |>
              st_transform(32637) |>
              st_buffer(50) |> st_union()) |> nrow()

wb100_osm <- osm_schools |> st_transform(32637) |>
  st_filter(schools_wb |>
              st_transform(32637) |>
              st_buffer(100) |> st_union()) |> nrow()


wb500_osm <- osm_schools |> st_transform(32637) |>
  st_filter(schools_wb |>
              st_transform(32637) |>
              st_buffer(500) |> st_union()) |> nrow()


wb1000_osm  <- osm_schools |> st_transform(32637) |>
  st_filter(schools_wb |>
              st_transform(32637) |>
              st_buffer(1000) |> st_union()) |> nrow()

osm50_wb <- schools_wb |> st_transform(32637) |>
  st_filter(osm_schools |>
              st_transform(32637) |>
              st_buffer(50) |> st_union()) |> nrow()

osm100_wb <- schools_wb |> st_transform(32637) |>
  st_filter(osm_schools |>
              st_transform(32637) |>
              st_buffer(100) |> st_union()) |> nrow()


osm500_wb <- schools_wb |> st_transform(32637) |>
  st_filter(osm_schools |>
              st_transform(32637) |>
              st_buffer(500) |> st_union()) |> nrow()


osm1000_wb  <- schools_wb |> st_transform(32637) |>
  st_filter(osm_schools |>
              st_transform(32637) |>
              st_buffer(1000) |> st_union()) |> nrow()

1 Overlap of schools in different datasets

Total amount of schools per dataset.

Dataset Total amount of schools
OSM 1759
Worldbank 2142

Overlap by distance from Wordlbank

Coverage of WB 50m % 100m % 500m % 1000m %
OSM 349 19.84 809 45.99 1722 97.9 1748 99.37

Overlap by distance from OpenStreetMap

Coverage of OSM 50m % 100m % 500m % 1000m %
WB 260 14.78 526 29.9 1587 90.22 1903 108.19

2 Comparing locations of schools

tmap_mode("view")

m.1 <- tm_basemap("OpenStreetMap") +
  tm_shape(osm_schools) +
  tm_dots(
    col="turquoise",
    size = .1,
    border.lwd = 0,
    popup.vars = c("osm_id", "amenity", "name", "education:students")
  )

m.2 <- tm_basemap("OpenStreetMap") +
  tm_shape(schools_wb) +
  tm_dots(
    col="firebrick",
    size = .1,
    border.lwd = 0,
    popup.vars = c("SCHOOL_NAM", "LEVEL", "Status", "Source")
  )

tmap_arrange(m.1,m.2, sync = T)

3 Aggregated on Hex grid

Also added a difference and worldpop map.

colrmp <- viridisLite::cividis(7)
colrmp[1] <- "#FFFFFF"



tmap_mode("view")

m.1 <- tm_basemap("OpenStreetMap") +
  tm_shape(hex_grid) +
  tm_polygons(
    title = "Schools in WB",
    col="count_wb",
    border.lwd = .1,
    breaks=c(0,1, 10, 20, 30, 50, 100, 150),
    palette=colrmp
  )

m.2 <- tm_basemap("OpenStreetMap") +
  tm_shape(hex_grid) +
  tm_polygons(
    title = "Schools in OSM",
    col="count_osm",
    border.lwd = .1,
    breaks=c(0,1, 10, 20, 30, 50, 100, 150),
    palette=colrmp
  )

m.3 <- tm_basemap("OpenStreetMap") +
  tm_shape(hex_grid) +
  tm_polygons(
    title = "WB - OSM counts",
    col="count_diff_wb_osm",
    breaks=c(-100,-50,-10,-1,0,1,10,50,100),
    border.lwd = .1,
    palette="RdBu"
  )

m.4 <- tm_basemap("OpenStreetMap") +
  tm_shape(hex_grid) +
  tm_polygons(
    title = "Population WorldPop",
    col="wpop",
    border.lwd = .1,
    breaks=c(0, 1, 100, 1000, 10000, 50000, 150000),
    palette=colrmp
  )

tmap_arrange(m.1,m.2,m.3,m.4,ncol = 2, nrow = 2, sync = T)